package com.yy.yyui.scroll
{
	import com.siku.manor.common.ArrayTools;
	import com.siku.manor.view.common.UM;
	import com.siku.manor.view.component.GT;
	import com.siku.manor.view.component.IActionList;
	import com.siku.manor.view.component.IGrid;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import gs.TweenLite;
	import gs.easing.Quad;

	public class ScrollTable extends Sprite implements IActionList
	{
		
		private var w:Number,h:Number;
		private var _actions:Object;
		
		private var _grid:IGrid;
		private var _contentPanel:Sprite;
		private var _scrollRectObject:DisplayObject;
		private var topPanel:Sprite;
		
		private var _speed:Number;
		
		private var _gap:Number;
		
		private var ubtn:SimpleButton,dbtn:SimpleButton,lbtn:SimpleButton,rbtn:SimpleButton;
		
		private var horizontal:Boolean;
		private var vertical:Boolean;
		public function ScrollTable(w:Number,h:Number,vertical:Boolean = true,horizontal:Boolean = false,gap:Number= 5)
		{

			//TODO: implement function
			super();
			this.w = w;
			this.h = h;
			this.vertical = vertical;
			this.horizontal = horizontal;
			this._gap = gap;
			var dobj:DisplayObject;
			var btn:SimpleButton;
			var sp:Sprite;				

			sp = new Sprite();
			this.addChild(sp);
			this._contentPanel = sp;

			
			//add buttons
			sp = new Sprite();
			dobj = this.addChild(sp);
			this.topPanel = sp;
			
			btn = UM.createScrollButton(UM.SCROLLBUTTON_UP);
			dobj = btn;
			dobj.x = (this.width - dobj.width)/2;
			this.ubtn = btn;
			
			btn = UM.createScrollButton(UM.SCROLLBUTTON_DOWN);
			dobj = btn;
			dobj.x = ubtn.x;
			dobj.y = (this.height- dobj.height);
			this.dbtn = btn;
			
			btn = UM.createScrollButton(UM.SCROLLBUTTON_LEFT);
			dobj = btn;
			dobj.y = (this.height- dobj.height)/2;
			this.lbtn = btn;
			
			btn = UM.createScrollButton(UM.SCROLLBUTTON_RIGHT);
			dobj = btn;
			dobj.x = this.width-dobj.width;
			dobj.y = lbtn.y;
			this.rbtn = btn;			
			
			if(horizontal){
				this.topPanel.addChild(lbtn);
				this.topPanel.addChild(rbtn);
			}			
			if(vertical){
				this.topPanel.addChild(ubtn);
				this.topPanel.addChild(dbtn);
			}
			

			
			var lRect:Rectangle = this.lbtn.getBounds(this);
			var rRect:Rectangle = this.rbtn.getBounds(this);
			var uRect:Rectangle = this.ubtn.getBounds(this);
			var dRect:Rectangle = this.dbtn.getBounds(this);
			
			
			//mask
			var maskWidth:Number,maskHeight:Number;
			if(horizontal){
				this.contentPanel.x = lRect.right+gap;
				maskWidth = rRect.left-lRect.right - gap*2;
			}else{
				this.contentPanel.x = 0;
				maskWidth = this.width;
			}
			if(vertical){
				this.contentPanel.y = uRect.bottom + gap;
				maskHeight = dRect.top - uRect.bottom - gap*2; 
			}else{
				this.contentPanel.y = 0;
				maskHeight = this.height;
			}
			this.contentPanel.scrollRect = new Rectangle(0,0,maskWidth,maskHeight);
			//GT.fulFill4(this.contentPanel,this.contentPanel.scrollRect,0x0,0);
			
			
			//set actions
			this._actions = {};
			this.enableButtons = true;
			this.speed =  0.2;
			
			//test
//			GT.fulFill3(this.contentPanel,maskWidth,maskHeight,0xff,0.5);
//			GT.fulFill3(this.topPanel,this.width,this.height,0x000000,0.5);
		}
		
		private function set enableButtons(value:Boolean):void{
			if(value){
				this.ubtn.addEventListener(MouseEvent.CLICK,this.onClickDown);
				this.dbtn.addEventListener(MouseEvent.CLICK,this.onClickDown);
				this.lbtn.addEventListener(MouseEvent.CLICK,this.onClickDown);
				this.rbtn.addEventListener(MouseEvent.CLICK,this.onClickDown);
				this.addEventListener(MouseEvent.MOUSE_WHEEL,this.onClickDown);
			}else{
				this.ubtn.removeEventListener(MouseEvent.CLICK,this.onClickDown);
				this.dbtn.removeEventListener(MouseEvent.CLICK,this.onClickDown);
				this.lbtn.removeEventListener(MouseEvent.CLICK,this.onClickDown);
				this.rbtn.removeEventListener(MouseEvent.CLICK,this.onClickDown);
				this.removeEventListener(MouseEvent.MOUSE_WHEEL,this.onClickDown);
				
			}
			
		}
		
		private static const disableAlpha:Number =0.3;
		public function checkArrowButtons():void{
			var locations:Array = this.grid.cellLocations;
			var bound:Rectangle = getLoactionsBound(locations);
			if(horizontal){
				if(bound.width<=this.scrollRectObject.scrollRect.width){
					this.lbtn.alpha = this.rbtn.alpha = disableAlpha;
				}else{
					this.lbtn.alpha = (bound.left<this.scrollRectObject.scrollRect.left)?1:disableAlpha;
					this.rbtn.alpha = (bound.right>this.scrollRectObject.scrollRect.right)?1:disableAlpha;
				}
			}
			if(vertical){
				if(bound.height<=this.scrollRectObject.scrollRect.height){
					this.ubtn.alpha = this.dbtn.alpha = disableAlpha;
				}else{
					this.ubtn.alpha = (bound.top<this.scrollRectObject.scrollRect.top)?1:disableAlpha;
					this.dbtn.alpha = (bound.bottom>this.scrollRectObject.scrollRect.bottom)?1:disableAlpha;
				}
			}
		}
		
		private function onClickDown(e:MouseEvent):void{
			this.enableButtons = false;
			var locations:Array = this.grid.cellLocations;
			var rect:Rectangle = this.scrollRectObject.scrollRect;
			currentX = rect.x;
			currentY = rect.y;			
			var bound:Rectangle = getLoactionsBound(locations);
			var nextX:Object,nextY:Object; 
			var p:Point = findCurrentCell(locations,rect);
			if(e.type == MouseEvent.MOUSE_WHEEL){
				if(e.delta>0){
					nextY = findNextDown(locations,rect,bound,p);
				}else{
					nextY = findNextUp(locations,rect,bound,p);
				}
			}else{
				switch(e.target){
					case this.ubtn:
						nextY = findNextDown(locations,rect,bound,p);
						break;
					case this.dbtn:
						nextY = findNextUp(locations,rect,bound,p);
						break;
					case this.lbtn:
						nextX = findNextRight(locations,rect,bound,p);
						break;
					case this.rbtn:
						nextX = findNextLeft(locations,rect,bound,p);
						break;
				}				
			}
			
								
			var obj:Object = new Object();
			obj.onUpdate = onScrollUpdate;			
			obj.onComplete = onScrollComplete;
			obj.ease = Quad.easeInOut;			
			if(nextX!=null||nextY!=null){
				if(nextX!=null){
					obj.currentX = Number(rect.x+nextX);
				}else if(nextY!=null){
					obj.currentY = Number(rect.y+nextY);
				}
				TweenLite.to(this,this.speed,obj);				
			}else{
				this.enableButtons = true;
			}					
		}

		public var currentX:Object;
		public var currentY:Object;	
		
		public function onScrollUpdate():void{
			var rect:Rectangle = this.scrollRectObject.scrollRect;
			
			if(currentX!=null){
				rect.x = currentX as Number;
			}
			if(currentY!=null){
				rect.y = currentY as Number;
			}
			
			this.scrollRectObject.scrollRect = rect;
		}			
		
		public function onScrollComplete():void{
			this.enableButtons = true;
			checkArrowButtons();
		}



//		private var tweening:TweenLite;
//		private var tempSpeed:Number = 0;;
//		private var userBreak:Boolean = false;
//		private var isOnClick:Boolean = false;
//		private function onClickDown(e:MouseEvent):void{
//			if(this.tweening!=null&&this.tweening.enabled){
//				return;
//			}
//			isOnClick = true;
//			move(e);
//		}
//		
//		private function move(e:MouseEvent):void{
//			if(userBreak) {
//				TweenLite.removeTween(this.tweening);
//				this.stage.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
//				tempSpeed = 0;				
//				userBreak = false;
//				isOnClick = false;
//				return;
//			}
//			this.stage.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
//			var obj:Object = new Object();
//			obj.onUpdate = onScrollUpdate;
//			obj.onComplete = onScrollComplete;
//			obj.onCompleteParams = [e];
//			obj.ease = Quad.easeInOut;
//			var locations:Array = this.grid.cellLocations;
//			var rect:Rectangle = this.scrollRectObject.scrollRect;
//			currentX = rect.x;
//			currentY = rect.y;
//			var p:Point = findCurrentCell(locations,rect);
//			var bound:Rectangle = getLoactionsBound(locations);
//			var dist:Number;
//			var nextX:Object,nextY:Object; 
//			switch(e.target){
//				case this.ubtn:
//					nextY = findNextDown(locations,rect,bound,p);
//					break;
//				case this.dbtn:
//					nextY = findNextUp(locations,rect,bound,p);
//					break;
//				case this.lbtn:
//					nextX = findNextRight(locations,rect,bound,p);
//					break;
//				case this.rbtn:
//					nextX = findNextLeft(locations,rect,bound,p);
//					break;
//			}
//			if(nextX!=null||nextY!=null){
//				if(tempSpeed==0){
//					tempSpeed = speed;
//				}else{
//					tempSpeed = tempSpeed*0.8;
//				}
//				if(nextX!=null){
//					obj.currentX = Number(rect.x+nextX);
//				}else if(nextY!=null){
//					obj.currentY = Number(rect.y+nextY);
//				}
//				this.tweening = TweenLite.to(this,tempSpeed,obj);
//			}
//			else{
//				TweenLite.removeTween(this.tweening);
//				userBreak = true;
//			}
//		}
//
//		private function onMouseUp(e:MouseEvent):void{
//			this.stage.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
//			tempSpeed = 0;				
//			userBreak = true;
//			isOnClick = false;
//		} 
//
//		public function onScrollComplete(e:MouseEvent):void{
//			move(e);
//			userBreak = false;
//		}
//
//		
//		public function onScrollUpdate():void{
//			var rect:Rectangle = this.scrollRectObject.scrollRect;
//			
//			if(currentX!=null){
//				rect.x = currentX as Number;
//			}
//			if(currentY!=null){
//				rect.y = currentY as Number;
//			}
//			
//			this.scrollRectObject.scrollRect = rect;
//		}
		

		private function findNextDown(locations:Array,sRect:Rectangle,bound:Rectangle,current:Point):Object{
			var i:int,il:int,j:int,jl:int;
			//find movable distance
			var dist:Number = bound.top - sRect.top;
			var rect:Rectangle;
			if(dist<0){
				for(i=current.y-1,il=0;i>=il;i--){
					rect = ArrayTools.getValue(locations,i,current.x) as Rectangle;
					if((rect.top - sRect.top)>dist&&(rect.top - sRect.top)<0){
						dist = (rect.top - sRect.top);
					}
				}
				return dist;					
			}
			return null;			
		}
		
		private function findNextUp(locations:Array,sRect:Rectangle,bound:Rectangle,current:Point):Object{
			var i:int,il:int,j:int,jl:int;
			//find movable distance
			var dist:Number = bound.bottom - sRect.bottom;
			var rect:Rectangle;
			if(dist>0){
				for(i=current.y+1,il=locations.length;i<il;i++){
					rect = ArrayTools.getValue(locations,i,current.x) as Rectangle;
					if((rect.top - sRect.top)<dist&&(rect.top - sRect.top)>0){
						dist = (rect.top - sRect.top);
					}
				}
				return dist;					
			}
			return null;			
		}
		
		private function findNextLeft(locations:Array,sRect:Rectangle,bound:Rectangle,current:Point):Object{
			var i:int,il:int,j:int,jl:int;
			//find movable distance
			var dist:Number = bound.right - sRect.right;
			var rect:Rectangle;
			if(dist>0){
				for(i=current.x+1,il=locations[current.y].length;i<il;i++){
					rect = ArrayTools.getValue(locations,current.y,i) as Rectangle;
					if((rect.left - sRect.left)<dist&&(rect.left - sRect.left)>0){
						dist = rect.left - sRect.left;
					}
				}
				return dist;
			}
			return null;
		}
		
		private function findNextRight(locations:Array,sRect:Rectangle,bound:Rectangle,current:Point):Object{
			var i:int,il:int,j:int,jl:int;
			//find movable distance
			var dist:Number = bound.left - sRect.left;
			var rect:Rectangle;
			if(dist<0){
				for(i=current.x-1,il=0;i>=il;i--){
					rect = ArrayTools.getValue(locations,current.y,i) as Rectangle;
					if((rect.left - sRect.left)>dist&&(rect.left - sRect.left)<0){
						dist = rect.left - sRect.left;
					}					
				}
				return dist;
			}		
			return null;
		}
		
		private function getLoactionsBound(locations:Array):Rectangle{
			var rectBound:Rectangle = new Rectangle(0,0,0,0);
			var i:uint,il:uint,j:uint,jl:uint;
			for(i=0,il=locations.length;i<il;i++){
				for(j=0,jl=locations[i].length;j<jl;j++){
						var rect:Rectangle = locations[i][j] as Rectangle;
						rectBound.left = Math.min(rect.left,rectBound.left);
						rectBound.right = Math.max(rect.right,rectBound.right);
						rectBound.top = Math.min(rect.top,rectBound.top);
						rectBound.bottom = Math.max(rect.bottom,rectBound.bottom);
				}
			}
			return rectBound;
		}
		
		private function findCurrentCell(locations:Array,sRect:Rectangle):Point{
			var p:Point = new Point();
			var i:uint,il:uint,j:uint,jl:uint;
			var minDist:Number = Number.MAX_VALUE;
			for(i=0,il=locations.length;i<il;i++){
				for(j=0,jl=locations[i].length;j<jl;j++){
					var rect:Rectangle = locations[i][j] as Rectangle;
					var ir:Rectangle = rect.intersection(sRect);
					if(ir.width==0||ir.height==0) continue;
					var centerX:Number = rect.x+rect.width/2;
					var centerY:Number = rect.y+rect.height/2;
					var dist:Number = (sRect.x-centerX)*(sRect.x-centerX)+(sRect.y-centerY)*(sRect.y-centerY);
					if(dist<minDist){
						p.x = j;
						p.y = i;
						minDist = dist;
					}
				}
			}
			return p;
		}
		



		
		public function attachGrid(value:IGrid,container:DisplayObjectContainer = null):void{
			this._grid = value;
			this._scrollRectObject = container==null?this.contentPanel:container;
			var rect:Rectangle = ArrayTools.getValue(this.grid.cellLocations,0,0) as Rectangle;
			if(rect==null){
				rect = new Rectangle(0,0,1,1);
			}
			var sRect:Rectangle = this.scrollRectObject.scrollRect;
			sRect.x = rect.x;
			sRect.y = rect.y;
			this.scrollRectObject.scrollRect = sRect;
			checkArrowButtons();
		}
		
		public function get speed():Number{return this._speed;}
		public function set speed(value:Number):void{this._speed = value;}
		
		public function get grid():IGrid{return this._grid;}
		public function get scrollRectObject():DisplayObject{return this._scrollRectObject;}
		
		public function get gap():Number{return this._gap;} 
		public function get contentPanel():Sprite{return this._contentPanel;}
		
		public function get actions():Object{return this._actions;}

		override public function get width():Number{return w;}
		override public function get height():Number{return h;}
		
		override public function set width(newWidth : Number) : void {
			var diff:Number = newWidth - w;
			var oldW:Number,oldH:Number;
			var i:uint,l:uint;			
			if(this.ubtn.parent!=null){
				this.ubtn.x+=diff/2;
				this.dbtn.x+=diff/2;
			}
			if(this.dbtn.parent!=null){
				this.rbtn.x+=diff;
			}
			var rect:Rectangle = this.contentPanel.scrollRect;
			rect.width+=diff;
			this.contentPanel.scrollRect =rect;			
			w = newWidth;
			checkArrowButtons();
//			this.ubtn.x = (this.width-this.ubtn.width)/2;
//			this.dbtn.x = (
		}
		
		override public function set height(newHeight : Number) : void {
			var diff:Number = newHeight - h;
			var oldW:Number,oldH:Number;
			var i:uint,l:uint;			
			if(this.lbtn.parent!=null){
				this.lbtn.y+=diff/2;
				this.rbtn.y+=diff/2;
			}
			if(this.dbtn.parent!=null){
				this.dbtn.y+=diff;
			}
			var rect:Rectangle = this.contentPanel.scrollRect;
			rect.height+=diff;
			this.contentPanel.scrollRect =rect;
			h = newHeight;
			checkArrowButtons();
		}
		
		override public function getBounds(targetCoordinateSpace:DisplayObject):Rectangle{
			return this.topPanel.getBounds(targetCoordinateSpace);			
		}
		
		override public function getRect(targetCoordinateSpace:DisplayObject):Rectangle{
			return this.topPanel.getRect(targetCoordinateSpace);
		}
		


	}
}